package com.iot08.admin.service;

import com.iot08.admin.service.page.PageVO;
import com.iot08.admin.service.page.PageableImpl;
import com.iot08.common.constant.Const;
import com.iot08.common.entity.admin.ChannelArea;
import com.iot08.common.entity.admin.SysUser;
import com.iot08.common.entity.app.Device;
import com.iot08.common.response.Response;
import com.iot08.common.service.base.BaseAdminService;
import com.iot08.common.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * @version 1.0
 * @Description: 角色业务处理
 * @author: Rock
 * @time: 2020/8/20 9:51
 */
@Slf4j
@Service
public class ChannelAreaService extends BaseAdminService<ChannelArea> {

    @Resource
    private UserService userService;
    @Resource
    private OperationService operationService;
    @Resource
    private DeviceService deviceService;

    /**
     * @param page
     * @time: 2020/12/7 11:35
     * @author: Rock
     * @version 1.0
     */
    public Page<ChannelArea> list(PageVO page, SysUser user) {
        PageableImpl pageable = new PageableImpl();
        page.setSort(Sort.by(Order.desc("create_time")));
        pageable.setPage(page);
        Criteria criteria = new Criteria().and("deleted").is(0).and("pid").exists(false);
        if (user.getType() == Const.CHANNELUSER_TYPE) {
            criteria.and("channel_code").in(user.getChannelAff().getChannelCodes());
        }
        Query query = new Query().addCriteria(criteria);
        long count = this.count(query);
        page.setTotalResult((int) count);
        List<ChannelArea> list = this.find(query.with(pageable));
        Page<ChannelArea> result = new PageImpl<ChannelArea>(list, pageable, count);
        for (ChannelArea channelArea : list) {
            criteria = Criteria.where("tid").is(channelArea.getId()).and("deleted").is(0);
            query = new Query(criteria).with(Sort.by(Order.desc("create_time")));
            List<ChannelArea> channelAreaList = this.find(query);
            createTree(channelArea, channelAreaList, new ArrayList<>());
        }
        return result;
    }

    /**
     * 树结构
     *
     * @param channelArea
     * @param channelAreaList
     * @time: 2020/12/8 11:08
     * @author: Rock
     * @version 1.0
     */
    private void createTree(ChannelArea channelArea, List<ChannelArea> channelAreaList, List<String> ids) {
        for (ChannelArea temp : channelAreaList) {
            if (channelArea.getId().equals(temp.getPid())) {
                channelArea.getChannelAreaList().add(temp);
                temp.setPname(channelArea.getName());
                createTree(temp, channelAreaList, ids);
                ids.add(temp.getId());
            }
        }
    }

    /**
     * @param id
     * @param user
     * @param ip
     * @time: 2020/12/7 11:39
     * @author: Rock
     * @version 1.0
     */
    public Response<Object> updateDel(String id, SysUser user, String ip) {
        ChannelArea channelArea = this.findById(id);
        if (channelArea == null) {
            log.error("ChannelArea is null. id={}", id);
            return Response.failedResponse();
        }
        Query query = new Query(Criteria.where("pid").is(id).and("deleted").is(0));
        ChannelArea parea = this.findOne(query);
        if (parea != null) {
            return Response.failedResponse("存在下级区域，无法删除");
        }
        query = new Query(Criteria.where("channel_area_id").is(id));
        //检查设备引用
        Device device = deviceService.findOne(query);
        if (device != null) {
            return Response.failedResponse("存在设备引用该区域，无法删除");
        }
        //检查账号引用
        query = new Query(Criteria.where("channel_area_id").is(id).and("deleted").is(0));
        SysUser u = userService.findOne(query);
        if (u != null) {
            return Response.failedResponse("存在账号引用该区域，无法删除");
        }
        Update update = new Update();
        update.set("deleted", 1);
        update.set("update_time", new Date());
        this.updateById(id, update);
        operationService.add(user, ip, "区域管理", "删除", "删除区域 ：" + channelArea.getName());
        return Response.successResponse();
    }

    /**
     * 生产id值
     *
     * @param level
     * @param pid
     * @time: 2020/12/7 14:21
     * @author: Rock
     * @version 1.0
     */
    public String createId(int level, String pid) {
        long count = countByPid(pid);
        String number = String.valueOf(++count);
        if (count <= 9) {
            number = "00" + number;
        } else if (count <= 99) {
            number = "0" + number;
        }
        switch (level) {
            case 1:
                return number + "000000000000";
            case 2:
                if (pid != null && pid.length() >= 15) {
                    return pid.substring(0, 3) + number + "000000000";
                }
            case 3:
                if (pid != null && pid.length() >= 15) {
                    return pid.substring(0, 6) + number + "000000";
                }
            case 4:
                if (pid != null && pid.length() >= 15) {
                    return pid.substring(0, 9) + number + "000";
                }
            case 5:
                if (pid != null && pid.length() >= 15) {
                    return pid.substring(0, 12) + number;
                }
            default:
                log.error("createId is error. level = {}", level);
        }
        return null;
    }

    /**
     * @param channelArea
     * @param user
     * @param ip
     * @time: 2020/12/7 14:27
     * @author: Rock
     * @version 1.0
     */
    public void save(ChannelArea channelArea, SysUser user, String ip) {
        if (channelArea != null) {
            if (StringUtil.isNotBlank(channelArea.getPid())) {
                ChannelArea ca = this.findById(channelArea.getPid());
                if (ca == null) {
                    return;
                }
                if (StringUtil.isBlank(ca.getTid())) {
                    channelArea.setTid(ca.getId());
                } else {
                    channelArea.setTid(ca.getTid());
                }
                channelArea.setChannelCode(ca.getChannelCode());
            }
            int level = channelArea.getLevel() == null ? 1 : channelArea.getLevel();
            channelArea.setId(createId(level, channelArea.getPid()));
            channelArea.setDeleted(0);
            channelArea.setCreateTime(new Date());
            mongoTemplate.save(channelArea);
            operationService.add(user, ip, "区域管理", "添加", "添加区域 ：" + channelArea.getName());
        }
    }

    /**
     * @Description: 更新
     * @time: 2020/8/18 10:41
     * @author: Rock
     * @version 1.0
     */
    public void update(ChannelArea channelArea, SysUser user, String ip) {
        if (channelArea != null) {
            Update update = new Update();
            update.set("name", channelArea.getName());
            update.set("update_time", new Date());
            this.updateById(channelArea.getId(), update);
            operationService.add(user, ip, "区域管理", "编辑", "编辑区域 ：" + channelArea.getName());
        }
    }

    /**
     * 添加一级渠道区域
     *
     * @param name
     * @param channelId
     * @param user
     * @param ip
     * @time: 2020/12/7 14:24
     * @author: Rock
     * @version 1.0
     */
    public void addLevel_1(Long channelCode, String name, SysUser user, String ip) {
        ChannelArea channelArea = new ChannelArea();
        channelArea.setName(name);
        channelArea.setChannelCode(channelCode);
        channelArea.setLevel(1);
        this.save(channelArea, user, ip);
    }

    /**
     * @param pid
     * @time: 2020/12/7 14:11
     * @author: Rock
     * @version 1.0
     */
    public long countByPid(String pid) {
        Query query = new Query();
        Criteria criteria = new Criteria();
        if (StringUtil.isBlank(pid)) {
            criteria.and("pid").exists(false);
        } else {
            criteria.and("pid").is(pid);
        }
        return this.count(query.addCriteria(criteria));
    }

    /**
     * @param level
     * @param user
     * @time: 2020/12/9 15:33
     * @author: Rock
     * @version 1.0
     */
    public List<ChannelArea> listByLevel(int level, SysUser user, boolean isFive) {
        List<ChannelArea> list = new ArrayList<>();
        Query query = new Query();
        Criteria criteria = Criteria.where("deleted").is(0);
        if (user.getChannelAreaId() != null) {
            criteria.and("pid").is(user.getChannelAreaId());
        } else {
            criteria.and("level").is(level + 1);
            if (user.getChannelAff() != null) {
                criteria.and("channel_code").in(user.getChannelAff().getChannelCodes());
            }
        }
        list = this.find(query.addCriteria(criteria));
        query = new Query();
        criteria = Criteria.where("deleted").is(0);
        if (!isFive) {
            criteria.andOperator(Criteria.where("level").gt(level + 1), Criteria.where("level").lt(5));
        }
        if (level > 1) {
            criteria.and("channel_code").is(user.getChannelArea().getChannelCode());
        } else {
            if (user.getChannelAff() != null) {
                criteria.and("channel_code").in(user.getChannelAff().getChannelCodes());
            }
        }
        List<ChannelArea> listAll = this.find(query.addCriteria(criteria));
        for (ChannelArea area : list) {
            createTree(area, listAll, new ArrayList<>());
        }
        return list;
    }

    /**
     * @param id
     * @param isFive
     * @time: 2020/12/15 19:13
     * @author: Rock
     * @version 1.0
     */
    public List<ChannelArea> listById(String id) {
        List<ChannelArea> res = new ArrayList<>();
        ChannelArea area = this.findById(id);
        if (area != null) {
            Query query = new Query(Criteria.where("level").gte(area.getLevel())
                    .and("deleted").is(0).and("channel_code").in(area.getChannelCode()));
            List<ChannelArea> listAll = this.find(query);
            createTree(area, listAll, new ArrayList<>());
            res.add(area);
        }
        return res;
    }

    /**
     * @param id
     * @time: 2020/12/17 11:48
     * @author: Rock
     * @version 1.0
     */
    public List<String> listIdById(String id, boolean isIncloud) {
        List<String> res = new ArrayList<>();
        ChannelArea area = this.findById(id);
        if (area != null) {
            Query query = new Query(Criteria.where("level").gte(area.getLevel())
                    .and("deleted").is(0).and("channel_code").in(area.getChannelCode()));
            List<ChannelArea> listAll = this.find(query);
            createTree(area, listAll, res);
            if (isIncloud) {
                res.add(id);
            }
        }
        return res;
    }

    /**
     * 根据级别获取下级的所有区域id
     *
     * @param level
     * @param user
     * @time: 2020/12/9 18:28
     * @author: Rock
     * @version 1.0
     */
    public List<String> listIdByLevel(int level, SysUser user) {
        //获取当前账号渠道列表
        Criteria criteria = Criteria.where("level").gte(level).and("deleted").is(0);
        if (user.getChannelArea() != null && user.getChannelArea().getLevel() > 1) {
            criteria.and("channel_code").is(user.getChannelArea().getChannelCode());
        } else {
            if (user.getChannelAff() != null) {
                criteria.and("channel_code").in(user.getChannelAff().getChannelCodes());
            }
        }
        List<String> result = new ArrayList<>();
        Query query = new Query();
        query.addCriteria(criteria);
        query.fields().include("_id");
        List<ChannelArea> list = this.find(query);
        for (ChannelArea area : list) {
            result.add(area.getId());
        }
        return result;
    }

    /**
     * 部分列表展示区域名称的处理
     *
     * @param area
     * @param userAreaLevel
     * @time: 2020/12/10 14:09
     * @author: Rock
     * @version 1.0
     */
    public void showNameHandle(ChannelArea area, int userAreaLevel) {
        if (area != null) {
            ChannelArea temp = null;
            StringBuilder name = new StringBuilder(area.getName());
            String pid = area.getPid();
            while (StringUtil.isNotBlank(pid)) {
                temp = this.findById(pid);
                if (temp != null) {
                    if (temp.getLevel() <= userAreaLevel) {
                        break;
                    }
                    name.insert(0, "/").insert(0, temp.getName());
                    pid = temp.getPid();
                } else {
                    pid = null;
                }
            }
            area.setName(name.toString());
        }
    }

}
